#if !defined(_CL_UTIL_H)
#define _CL_UTIL_H
#include <stdint.h>
#include <stdlib.h>

/**
 * @brief 获取数字的项目数量
 */
#define CL_ARRAY_CNT(X) (sizeof(X) / sizeof(X[0]))

#define CL_MAX(x, y) ((x) > (y) ? (x) : (y))

#define CL_MIN(x, y) ((x) < (y) ? (x) : (y))

/**
 * \brief   把数值限制在指定范围内（夹逼）
 * \param   x   要限制的数值
 * \param   min 最小值
 * \param   max 最大值
 * \return  若 x 在 min~max 之间，返回 x；
 *          x 小于 min，返回 min；
 *          x 大于 max，返回 max。
 * \note    不检查 min < max，由调用者保证。
 * \note    宏展开，结果类型与输入一致。
 */
#define CL_LIMIT(x, min, max) CL_MIN(CL_MAX((x), (min)), (max))

/**
 * \brief   把输入值按比例映射到新的范围
 *
 * 计算公式：
 *
 *            (x - in_min) * (out_max - out_min)
 *  y = -------------------------------------- + out_min
 *                   (in_max - in_min)
 *
 * \note    结果类型由输入参数决定。若需高精度，可先把参数转成 float/double；
 *          若只要整数精度，用整型即可。
 *
 * \note    映射后的值不会自动限制在 out_min 与 out_max 之间（可能超界）。
 *          如需限制，请再用 CL_LIMIT() 宏夹逼。
 *
 * \param   x        待映射的原始值
 * \param   in_min   原始范围最小值
 * \param   in_max   原始范围最大值
 * \param   out_min  目标范围最小值
 * \param   out_max  目标范围最大值
 * \return  映射后的值
 */
#define CL_VALUE_MAP(x, in_min, in_max, out_min, out_max)               \
  (((x) - (in_min)) * ((out_max) - (out_min)) / ((in_max) - (in_min)) + \
   (out_min))

#define CL_ABS(x) ((x) < 0 ? -(x) : (x))

#define CL_SET_ptr_Value(ptr, value) \
  do {                               \
    if ((prt) != NULL) {             \
      *(ptr) = (value);              \
    }                                \
  } while (0)

// #define CL_BIT_SET(v, mask) ((v) |= (mask))
// #define CL_BIT_CLEAR(v, mask) ((v) &= ~(mask))
// #define CL_BIT_READ(v, mask) ((v) & (mask))

// 将变量 var 的第 x 位设为 1
#define CL_SET_BIT(var, x) ((var) |= (1UL << (x)))
// 将变量 var 的第 x 位设为 0
#define CL_CLEAR_BIT(var, x) ((var) &= ~(1UL << (x)))
// 将变量 var 的第 x 位设为给定值 (bitVal: 0 或 1)
#define CL_WRITE_BIT(var, x, bitVal) \
  ((bitVal) ? SET_BIT(var, x) : CLEAR_BIT(var, x))
// 获取变量 var 的第 x 位的值 (0 或 1)
#define CL_GET_BIT(var, x) (((var) >> (x)) & 1UL)

#endif  // _CL_UTIL_H
